package com.allesblinkt.mucom.sketches;

import processing.core.PApplet;
import processing.core.PImage;
import traer.physics.*;
import traer.animation.*;

public class SketchCircles extends PApplet {
	public static void main(String[] args) {
		PApplet
				.main(new String[] { "com.allesblinkt.mucom.sketches.SketchCircles" });
	}

	final float NODE_SIZE = 4;
	final float EDGE_LENGTH = 30;
	final float EDGE_STRENGTH = 0.2f;
	final float SPACER_STRENGTH = 2000;

	ParticleSystem physics;
	Smoother3D centroid;

	PImage ClientRing;
	PImage DataRing;

	// PROCESSING /////////////////////////////////////

	public void setup() {
		size(400, 400);
		smooth();
		frameRate(24);
		strokeWeight(1);
		ellipseMode(CENTER);

		physics = new ParticleSystem(0, 0.25f);
		centroid = new Smoother3D(0.8f);

		ClientRing = loadImage("client/ClientRing.png");
		DataRing = loadImage("client/DataRing.png");

		initialize();
	}

	public void draw() {
		physics.tick(1.0f);
		if (physics.numberOfParticles() > 1)
			updateCentroid();
		centroid.tick();
		background(255);
		translate(width / 2, height / 2);
		// scale( centroid.z() );
		translate(-centroid.x(), -centroid.y());
		fill(200);
		drawNetwork();
	}

	void drawNetwork() {
		// draw vertices
		// fill( 50 );
		noStroke();
		for (int i = 0; i < physics.numberOfParticles(); ++i) {
			Particle v = physics.getParticle(i);
			Particle w = physics.getParticle(0);
			// fill( 50 );
			image(ClientRing, w.position().x() - 16, w.position().y() - 16);
			ellipse(w.position().x(), w.position().y(), NODE_SIZE, NODE_SIZE);
			image(DataRing, v.position().x() - 16, v.position().y() - 16);
			// fill(160);
			ellipse(v.position().x(), v.position().y(), NODE_SIZE, NODE_SIZE);
		}
		// draw line //////////////////////

		// draw edges
		stroke(0);
		beginShape(LINES);
		for (int i = 0; i < physics.numberOfSprings(); ++i) {
			Spring e = physics.getSpring(i);
			Particle a = e.getOneEnd();
			Particle b = e.getTheOtherEnd();

			vertex(a.position().x(), a.position().y());
			vertex(b.position().x(), b.position().y());
		}
		endShape();

	}

	public void keyPressed() {
		if (key == 'c') {
			initialize();
			return;
		}

		if (key == ' ') {
			addNode();
			return;
		}
	}

	// ME ////////////////////////////////////////////

	void updateCentroid() {
		float xMax = Float.NEGATIVE_INFINITY, xMin = Float.POSITIVE_INFINITY, yMin = Float.POSITIVE_INFINITY, yMax = Float.NEGATIVE_INFINITY;

		for (int i = 0; i < physics.numberOfParticles(); ++i) {
			Particle p = physics.getParticle(i);
			xMax = max(xMax, p.position().x());
			xMin = min(xMin, p.position().x());
			yMin = min(yMin, p.position().y());
			yMax = max(yMax, p.position().y());
		}
		float deltaX = xMax - xMin;
		float deltaY = yMax - yMin;
		if (deltaY > deltaX)
			centroid.setTarget(xMin + 0.5f * deltaX, yMin + 0.5f * deltaY,
					height / (deltaY + 50));
		else
			centroid.setTarget(xMin + 0.5f * deltaX, yMin + 0.5f * deltaY,
					width / (deltaX + 50));
	}

	// Anziehungskraft zwischen den Endpunkten
	void addSpacersToNode(Particle p, Particle r) {
		for (int i = 0; i < physics.numberOfParticles(); ++i) {
			Particle q = physics.getParticle(i);
			if (p != q && p != r)
				physics.makeAttraction(p, q, -SPACER_STRENGTH, 20);
		}
	}

	// Feder setzen
	void makeEdgeBetween(Particle a, Particle b) {
		physics.makeSpring(a, b, EDGE_STRENGTH, EDGE_STRENGTH, EDGE_LENGTH);
	}

	void initialize() {
		physics.clear();
		physics.makeParticle();
		centroid.setValue(0, 0, 1.0f);
	}

	void addNode() {
		Particle p = physics.makeParticle();
		Particle q = physics.getParticle(0);
		while (q == p)
			q = physics.getParticle(0);
		addSpacersToNode(p, q);
		makeEdgeBetween(p, q);
		p.moveTo(q.position().x() + random(-1, 1), q.position().y()
				+ random(-1, 1), 0);
	}

}